﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows;
using Wpf_Examples.Models;

namespace Wpf_Examples.Tools
{
    public class CreateParticleWaveEffectHelper
    {
        private readonly List<ParticleWaveEffectModel> _particleList; // 存储所有粒子的列表
        private readonly GeometryModel3D _particleModel; // 3D几何模型，用于绘制粒子
        private readonly int SEPARATION = 100; // 粒子之间的间距

        // 构造函数，初始化粒子波浪效果
        public CreateParticleWaveEffectHelper(int amountX, int amountY, Color color, int size)
        {
            XParticleCount = amountX; // X方向上的粒子数量
            YParticleCount = amountY; // Y方向上的粒子数量

            _particleList = new List<ParticleWaveEffectModel>(); // 初始化粒子列表

            _particleModel = new GeometryModel3D { Geometry = new MeshGeometry3D() }; // 初始化3D几何模型

            // 创建一个椭圆形状
            var e = new Ellipse
            {
                Width = size,
                Height = size
            };

            // 创建一个径向渐变刷
            var b = new RadialGradientBrush();
            b.GradientStops.Add(new GradientStop(Color.FromArgb(0xFF, color.R, color.G, color.B), 0.25)); // 中心颜色
            b.GradientStops.Add(new GradientStop(Color.FromArgb(0x00, color.R, color.G, color.B), 1.0)); // 边缘颜色
            e.Fill = b; // 设置椭圆的填充颜色
            e.Measure(new Size(size, size)); // 测量椭圆的大小
            e.Arrange(new Rect(0, 0, size, size)); // 安排椭圆的位置

            // 将椭圆渲染到一个RenderTargetBitmap对象中
            var renderTarget = new RenderTargetBitmap(size, size, 96, 96, PixelFormats.Pbgra32);
            renderTarget.Render(e);
            renderTarget.Freeze(); // 冻结BitmapSource对象，使其可以跨线程使用
            var brush = new ImageBrush(renderTarget); // 创建一个ImageBrush对象

            // 设置粒子模型的材质
            var material = new DiffuseMaterial(brush);
            _particleModel.Material = material;

            // 初始化粒子
            SpawnParticle(size);
        }

        public int XParticleCount { get; set; } // X方向上的粒子数量
        public int YParticleCount { get; set; } // Y方向上的粒子数量
        public Model3D ParticleModel => _particleModel; // 获取粒子模型
        private double _count = 0; // 用于波浪效果的时间计数器

        // 更新粒子位置和大小的方法
        public void Update()
        {
            // 计算每个粒子的新位置和大小
            for (int ix = 0; ix < XParticleCount; ix++)
            {
                for (int iy = 0; iy < YParticleCount; iy++)
                {
                    // 直接访问粒子列表中的元素
                    var index = iy * XParticleCount + ix;
                    var particle = _particleList[index];

                    // 计算新的Z坐标（高度）
                    particle.Position.Z = (Math.Sin((ix + _count) * 0.3) * 100) + (Math.Sin((iy + _count) * 0.5) * 100);
                    // 计算新的大小
                    particle.Size = (Math.Sin((ix + _count) * 0.3) + 1) * 8 + (Math.Sin((iy + _count) * 0.5) + 1) * 8;
                }
            }
            _count += 0.1; // 增加时间计数器

            UpdateGeometry(); // 更新几何体
        }

        // 更新几何体的方法
        private void UpdateGeometry()
        {
            var positions = new Point3DCollection(); // 存储所有粒子的位置
            var indices = new Int32Collection(); // 存储三角形索引
            var texcoords = new PointCollection(); // 存储纹理坐标

            // 清空旧的数据
            positions.Clear();
            indices.Clear();
            texcoords.Clear();

            // 遍历所有粒子，更新几何体数据
            for (var i = 0; i < _particleList.Count; ++i)
            {
                var particle = _particleList[i]; // 当前粒子
                var positionIndex = i * 4; // 当前粒子的顶点索引
                var indexIndex = i * 6; // 当前粒子的索引索引

                // 计算四个顶点的位置
                var p1 = new Point3D(particle.Position.X, particle.Position.Y, particle.Position.Z);
                var p2 = new Point3D(particle.Position.X, particle.Position.Y + particle.Size, particle.Position.Z);
                var p3 = new Point3D(particle.Position.X + particle.Size, particle.Position.Y + particle.Size, particle.Position.Z);
                var p4 = new Point3D(particle.Position.X + particle.Size, particle.Position.Y, particle.Position.Z);

                // 添加顶点位置
                positions.Add(p1);
                positions.Add(p2);
                positions.Add(p3);
                positions.Add(p4);

                // 计算纹理坐标
                var t1 = new Point(0.0, 0.0);
                var t2 = new Point(0.0, 1.0);
                var t3 = new Point(1.0, 1.0);
                var t4 = new Point(1.0, 0.0);

                // 添加纹理坐标
                texcoords.Add(t1);
                texcoords.Add(t2);
                texcoords.Add(t3);
                texcoords.Add(t4);

                // 添加三角形索引
                indices.Add(positionIndex);
                indices.Add(positionIndex + 2);
                indices.Add(positionIndex + 1);
                indices.Add(positionIndex);
                indices.Add(positionIndex + 3);
                indices.Add(positionIndex + 2);
            }

            // 更新几何体的数据
            ((MeshGeometry3D)_particleModel.Geometry).Positions = positions;
            ((MeshGeometry3D)_particleModel.Geometry).TriangleIndices = indices;
            ((MeshGeometry3D)_particleModel.Geometry).TextureCoordinates = texcoords;
        }

        // 初始化粒子的方法
        public void SpawnParticle(double size)
        {
            // 根据粒子数量和间距初始化粒子的位置和大小
            for (int ix = 0; ix < XParticleCount; ix++)
            {
                for (int iy = 0; iy < YParticleCount; iy++)
                {
                    var p = new ParticleWaveEffectModel
                    {
                        Position = new Point3D(ix * SEPARATION - ((XParticleCount * SEPARATION) / 2),
                                               iy * SEPARATION - ((YParticleCount * SEPARATION) / 2), 0),
                        Size = size,
                        IndexX = ix,
                        IndexY = iy,
                    };
                    _particleList.Add(p); // 将粒子添加到列表中
                }
            }
        }
    }
}